package com.huishi.ui.component;

import com.huishi.entity.DataSource;
import com.huishi.enums.TimeUnit;
import com.huishi.handler.thread.task.DataXIncrementalSyncTask;
import com.huishi.handler.thread.task.RecordDataXTaskInfo;
import com.huishi.mapper.DataXTaskInfoMapper;
import com.huishi.ui.DataSyncUI;
import com.huishi.util.JSONUtils;
import com.huishi.util.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.ScheduledExecutorService;

/**
 * 进度信息展示对话框
 */
//@Component
@Slf4j
public class IncrementalSyncDialog extends JFrame {

    @Autowired
    private DataSyncUI dataSyncUI;

    @Autowired
    private ScheduledExecutorService scheduler;

    @Autowired
    @Qualifier("threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor executor;

    @Autowired
    private DataXTaskInfoMapper dataXTaskInfoMapper;

    private long startTime; // 同步开始时间


    private JTextField taskNameField; // 任务名称
    private JTextField startTimeField; // 开始执行时间
    private JTextField intervalField; // 执行间隔时间
    private JComboBox<String> intervalUnitBox; // 执行间隔时间单位
    private JButton submitButton; // 提交任务按钮

    public IncrementalSyncDialog() {
        setTitle("增量同步");
        setSize(400, 200);
        setLocationRelativeTo(dataSyncUI);
        setVisible(false);

        // 禁用最大化按钮
        setResizable(false);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        taskNameField = new JTextField(20);

        // 开始执行时间
        startTimeField = new JTextField(20);
        startTimeField.setEditable(false);
        startTimeField.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent evt) {
                chooseStartTime();
            }
        });

        // 执行间隔时间
        intervalField = new JTextField(10);
        intervalField.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {

                String key = "0123456789";
                if (key.indexOf(e.getKeyChar()) < 0) {
                    e.consume();//如果不是数字则取消
                }
            }
        });
        intervalField.setText("60"); // 默认60秒

        // 执行间隔时间单位
        String[] intervalUnits = TimeUnit.getAllUnits();
        intervalUnitBox = new JComboBox<>(intervalUnits);

        // 提交按钮
        submitButton = new JButton("提交");

        JPanel controlPanel = new JPanel(new GridLayout(4, 4));
        controlPanel.add(new JLabel("任务名称:", SwingConstants.CENTER));
        controlPanel.add(taskNameField);
//        controlPanel.add(new Label());
        controlPanel.add(new JLabel("首次执行时间:", SwingConstants.CENTER));
        controlPanel.add(startTimeField);
        controlPanel.add(new JLabel("同步间隔时间:", SwingConstants.CENTER));

        JPanel intervalPanel = new JPanel(new BorderLayout());
        intervalPanel.add(intervalField, BorderLayout.CENTER);
        intervalPanel.add(intervalUnitBox, BorderLayout.EAST);
        controlPanel.add(intervalPanel);


        controlPanel.add(new Label());
        controlPanel.add(submitButton);

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(controlPanel, BorderLayout.CENTER);

        add(panel);

        // 按钮事件
        submitButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                startSync();
            }
        });

    }

    /**
     * 格式化经过的时间
     *
     * @param elapsedTime 经过的时间（毫秒）
     * @return 格式化后的时间字符串（时:分:秒）
     */
    private String formatElapsedTime(long elapsedTime) {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        Date date = new Date(elapsedTime);
        return format.format(date);
    }

    /**
     * 显示时间选择对话框
     */
    private void chooseStartTime() {
        JPanel panel = new JPanel(new GridLayout(2, 1));
        JSpinner dateSpinner = new JSpinner(new SpinnerDateModel());
        dateSpinner.setEditor(new JSpinner.DateEditor(dateSpinner, "yyyy-MM-dd"));

        JSpinner timeSpinner = new JSpinner(new SpinnerDateModel());
        timeSpinner.setEditor(new JSpinner.DateEditor(timeSpinner, "HH:mm:ss"));

        panel.add(dateSpinner);
        panel.add(timeSpinner);

        int result = JOptionPane.showOptionDialog(this, panel, "选择开始执行时间", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
        if (result == JOptionPane.OK_OPTION) {
            Date date = ((SpinnerDateModel) dateSpinner.getModel()).getDate();
            Date time = ((SpinnerDateModel) timeSpinner.getModel()).getDate();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            startTimeField.setText(dateFormat.format(date) + " " + new SimpleDateFormat("HH:mm:ss").format(time));
        }
    }

    /**
     * 开始增量同步任务
     */
    private void startSync() {
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date startDate = dateFormat.parse(startTimeField.getText());
            Long interval = Long.parseLong(intervalField.getText());
            String unit = (String) intervalUnitBox.getSelectedItem();

            startTime = startDate.getTime();
            log.info("首次同步时间：{}", startDate);
            log.info("增量同步时间间隔：{}{}", interval, unit);

            // 1、获取增量同步源数据库和目标数据库信息
            // 源信息
            DataSource source = (DataSource) dataSyncUI.getSourceConnCombo().getSelectedItem();
            JPanel sourceTablePanel = dataSyncUI.getSourceTablePanel();
            List<String> sourceTBs = new ArrayList<>();
            for (int i = 0; i < sourceTablePanel.getComponentCount(); i++) {
                JCheckBox selectedTB = (JCheckBox) sourceTablePanel.getComponent(i);
                if (selectedTB.isSelected()) {
                    sourceTBs.add(selectedTB.getText());
                }
            }
            assert source != null;
            log.info("源数据库信息：【sourceType】{}，【sourceName】{}，" +
                            "【sourceUrl】{}，【ip】{}，【port】{}，" +
                            "【schema】{}，【userName】{}，【password】{}，\n源表：{}",
                    source.getSourceType(), source.getSourceName(), source.getSourceUrl(), source.getIp(),
                    source.getPort(), source.getSchema(), source.getUserName(), source.getPassword(), sourceTBs);

            // 目标信息
            DataSource dataTarget = (DataSource) dataSyncUI.getTargetConnCombo().getSelectedItem();
            assert dataTarget != null;
            log.info("目标数据库信息：【sourceType】{}，【sourceName】{}，" +
                            "【sourceUrl】{}，【ip】{}，【port】{}，" +
                            "【schema】{}，【userName】{}，【password】{}",
                    dataTarget.getSourceType(), dataTarget.getSourceName(), dataTarget.getSourceUrl(), dataTarget.getIp(),
                    dataTarget.getPort(), dataTarget.getSchema(), dataTarget.getUserName(), dataTarget.getPassword());

            // 2、记录任务
            executor.submit(new RecordDataXTaskInfo(source, dataTarget, sourceTBs, "update_time", "update", startDate, interval.intValue(), TimeUnit.getValueByUnit(unit), dataXTaskInfoMapper));

            // 3、创建定时任务生成DataX的job.json，并执行job.json
            for (String sourceTB : sourceTBs) {
                long taskInterval = TimeUtils.conventTimeToMillion(interval, unit);
                long initialDelay = startTime - System.currentTimeMillis() > 0 ? startTime - System.currentTimeMillis() : 0;
                // 每张要增量同步的表都在独立的定时任务中执行
                scheduler.scheduleAtFixedRate(new DataXIncrementalSyncTask(source, dataTarget, sourceTB),
                        initialDelay, taskInterval, java.util.concurrent.TimeUnit.MILLISECONDS);
            }


        } catch (ParseException ex) {
            JOptionPane.showMessageDialog(this, "输入格式有误，请检查后重新输入。", "错误", JOptionPane.ERROR_MESSAGE);
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(this, "执行间隔时间输入有误，请输入有效的数字。", "错误", JOptionPane.ERROR_MESSAGE);
        }
    }


    public static void main(String[] args) {
        IncrementalSyncDialog dialog = new IncrementalSyncDialog();
        dialog.setVisible(true);
    }
}
